package com.nbst.comnutil;

import java.io.BufferedReader;
import java.io.File;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.alibaba.fastjson.JSON;
import com.nbst.model.base.MapModel;
import com.nbst.wx.TemplateData;

import org.apache.commons.collections4.CollectionUtils;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;

/**
 * @author King
 * @ClassName: ToolUtils
 * @Description:工具类
 * @date 2020年6月29日
 */
@Component
public class ToolUtils {

    private static String uploadPath;

    // @Value("${web.upload-path}")
    // public void setUploadPath(String url) {
    //     uploadPath = url;
    // }

    /**
     * 默认初始大小
     */
    public static final int DEFAULT_INITIAL_CAPACITY = 16;
    /**
     * 默认增长因子，当Map的size达到 容量*增长因子时，开始扩充Map
     */
    public static final float DEFAULT_LOAD_FACTOR = 0.75f;

    /**
     * @param files   上传你文件
     * @param Package 上传到哪个文件夹
     * @param name    文件名字
     * @return 返回路径
     */
    public static String isUploadfile(MultipartFile files, String Package, String name) {
        String file = null;
        if (!files.isEmpty() && Package != null) {
            try {
                if (name == null) {
                    name = DateTimeUtil.DateTime2String("yyyMMddHHmmss");
                }
                // imgPath为原文件名
                int idx = files.getOriginalFilename().lastIndexOf(".");
                // 文件后缀
                String extention = files.getOriginalFilename().substring(idx);
                file = name + extention;
                File f = new File(uploadPath + "/" + Package + "/", file);
                if (!f.getParentFile().exists()) {
                    f.getParentFile().mkdirs();
                }
                // 判断文件是否存在，存在覆盖
                if (f.exists()) {
                    f.delete();
                }
                files.transferTo(f);

            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        return file;
    }

    public static String isUploadfile2(MultipartFile files, String Package) {
        String file = null;
        if (!files.isEmpty() && Package != null) {
            try {
                file = files.getOriginalFilename();
                File f = new File(uploadPath + "/" + Package + "/", file);
                if (!f.getParentFile().exists()) {
                    f.getParentFile().mkdirs();
                }
                // 判断文件是否存在，存在覆盖
                if (f.exists()) {
                    f.delete();
                }
                files.transferTo(f);

            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        return file;
    }


    /**
     * 根据缓存中的消息体生成统一结构的返回消息
     *
     * @param message 缓存中的消息体
     * @return NormalResult 返回消息实体类
     * @author King
     * @date 2020年6月29日
     */
    public static NormalResult carertResult(String message) {
        NormalResult result = new NormalResult();
        return carertResult(message, result);

    }

    /**
     * 根据缓存中的消息体生成系统一结构的返回消息
     *
     * @param message 缓存中的消息体
     * @return NormalResult 返回消息实体类
     * @author King
     * @date 2020年6月29日
     */
    public static NormalResult carertResult(String message, NormalResult result) {
        if (result == null) {
            result = ToolUtils.getResult();
        }
        String code = "";
        String msg = "";
        if (!message.contains(":")) {
            if (isEmpty(message)) {
                message = "操作失败";
            }
            message = "9999:" + message;
        }

        String[] arrayStr = message.split(":");
        code = arrayStr[0];
        msg = arrayStr[1];
        result.setCode(code);
        if (!NumberUtil.isNumber(code)){
            result.setCode("9999");
            result.setMessage(message);
        }else{
            result.setMessage(msg);
        }
        return result;
    }


    /**
     * 根据缓存中的消息体生成系统一结构的返回消息
     *
     */
    public static NormalResult giveResult(String message, NormalResult result) {
        if (result == null) {
            result = ToolUtils.getResult();
        }
        String code = "";
        String msg = "";
        if (!message.contains(":")) {
            if (isEmpty(message)) {
                message = "操作失败";
                message = "9999:" + message;
            }
        }
        String[] arrayStr = message.split(":");
        code = arrayStr[0];
        msg = arrayStr[1];
        result.setCode(code);
        result.setMessage(msg);
        return result;
    }



    /**
     * 判断返回值是否为"0000"
     *
     * @param result
     * @return java.lang.Boolean
     * @author King
     * @date 2020/12/4 0004 17:16
     */
    public static Boolean isOk(NormalResult result) {
        if (result == null) {
            return false;
        }
        if (Constants.OK_CODE.equals(result.getCode())) {
            return true;
        } else {
            return false;
        }
    }

    public static Boolean isNotOk(NormalResult result) {
        return !isOk(result);
    }

    /**
     * 获取操作成功的返回信息
     * <p>
     * = * @return NormalResult
     *
     * @author King
     * @date 2020年7月6日
     */
    public static NormalResult getNormalResult() {
        NormalResult result = new NormalResult();
        result.setCode(Constants.DefaultResultEnums.SYSTEM_NORMAL.getCode());
        result.setMessage(Constants.DefaultResultEnums.SYSTEM_NORMAL.getName());
        return result;
    }

    /**
     * 获取操作成功的返回信息
     * <p>
     * = * @return NormalResult
     *
     * @author King
     * @date 2020年7月6日
     */
    public static NormalResult getNormalResult(String desc) {
        NormalResult result = new NormalResult();
        result.setCode(Constants.DefaultResultEnums.SYSTEM_NORMAL.getCode());
        result.setMessage(Constants.DefaultResultEnums.SYSTEM_NORMAL.getName());
        result.setDesc(desc);
        return result;
    }

    /**
     * 获取操作成功的返回信息
     *
     * @param result
     * @return NormalResult
     * @author King
     * @date 2020年7月6日
     */
    public static NormalResult getNormalResult(NormalResult result) {
        result.setCode(Constants.DefaultResultEnums.SYSTEM_NORMAL.getCode());
        result.setMessage(Constants.DefaultResultEnums.SYSTEM_NORMAL.getName());
        result.setId(result.getId());
        return result;
    }

    /**
     * 生成异常的封装返回结果对象(未找到对象)
     *
     * @param result
     * @return
     * @author lyw
     * @date 2020年7月10日
     */
    public static NormalResult getNotFindResult(NormalResult result) {
        result.setCode(Constants.DefaultResultEnums.NOT_FIND.getCode());
        result.setMessage(Constants.DefaultResultEnums.NOT_FIND.getName());
        return result;
    }

    /**
     * 生成异常的封装返回结果对象(操作失败)
     *
     * @return NormalResult
     * @author King
     * @date 2020年6月29日
     */
    public static NormalResult getResult() {
        NormalResult result = new NormalResult(Constants.DefaultResultEnums.SERVICE_ERROR.getCode(),
                Constants.DefaultResultEnums.SERVICE_ERROR.getName());
        return result;
    }

    /**
     * 生成异常的封装返回结果对象(操作失败)
     *
     * @return NormalResult
     * @author King
     * @date 2020年6月29日
     */
    public static NormalResult getResult(NormalResult result) {
        result.setCode(Constants.DefaultResultEnums.SERVICE_ERROR.getCode());
        result.setMessage(Constants.DefaultResultEnums.SERVICE_ERROR.getName());
        return result;
    }

    /**
     * 生成异常的封装返回结果对象(操作失败)
     *
     * @return NormalResult
     * @author King
     * @date 2020年6月29日
     */
    // public static NormalResult getErroResultByTransactionRollBack(NormalResult result) {
    //     result.setCode(Constants.DefaultResultEnums.SERVICE_ERROR.getCode());
    //     result.setMessage(Constants.DefaultResultEnums.SERVICE_ERROR.getName());
    //     return getByTransactionRollBack(result);
    // }

    /**
     * 获取操作成功的返回信息并将有用的数据存入row中
     *
     * @param result
     * @param row
     * @return
     * @author lyw
     * @date 2020年7月10日
     */
    public static NormalResult getNormalResult(NormalResult result, Object rows) {
        result.setCode(Constants.DefaultResultEnums.SYSTEM_NORMAL.getCode());
        result.setMessage(Constants.DefaultResultEnums.SYSTEM_NORMAL.getName());
        result.setRows(rows);
        return result;
    }

    /**
     * 获取操作错误信息（带手动回滚）
     *
     * @param result
     * @return NormalResult
     * @author King
     * @date 2020年7月6日
     */
    // public static NormalResult getResultByTransactionRollBack(NormalResult result) {
    //     //TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();// 手动回滚
    //     try {
    //         throw new MyException(result.getCode(), result.getMessage());
    //     } catch (MyException e) {
    //         // TODO Auto-generated catch block
    //         e.printStackTrace();
    //     }
    //     //return result;
    // }

    /**
     * 获取操作错误信息（带手动回滚）
     *
     * @param result
     * @return NormalResult
     */
    // public static NormalResult getByTransactionRollBack(NormalResult result) {
    //     //TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();// 手动回滚
    //     //return result;
    //     throw new MyException(result.getCode(), result.getMessage());
    // }

    /**
     * 处理消息并手动回滚
     *
     * @param message
     * @param result
     * @return
     */
    // public static NormalResult carertResultByTransactionRollBack(String message, NormalResult result) {
    //     if (result == null) {
    //         result = ToolUtils.getResult();
    //     }
    //     String code = "";
    //     String msg = "";
    //     if (!message.contains(":")) {
    //         if (isEmpty(message)) {
    //             message = "操作失败";
    //         }
    //         message = "9999:" + message;
    //     }
    //     String[] arrayStr = message.split(":");
    //     code = arrayStr[0];
    //     msg = arrayStr[1];
    //     result.setCode(code);
    //     result.setMessage(msg);
    //     throw new MyException(result.getCode(), result.getMessage());
    // }

    /**
     * 新建一个HashMap
     *
     * @param <K> Key类型
     * @param <V> Value类型
     * @return HashMap对象
     */
    public static <K, V> HashMap<K, V> newHashMap() {
        int initialCapacity = (int) (DEFAULT_INITIAL_CAPACITY / DEFAULT_LOAD_FACTOR);
        return new HashMap<K, V>(initialCapacity);
    }

    /**
     * java Bean转Map 忽略值为空的字段
     *
     * @param bean
     * @param targetMap
     * @return Map<String, Object>
     * @author King
     * @date 2020年7月8日
     */
    public static Map<String, Object> beanToMap(Object bean) {
        Map<String, Object> targetMap = newHashMap();
        return BeanUtil.beanToMap(bean, targetMap, false, true);

    }

    /**
     * 把字符串转换成bean对象
     *
     * @param str
     * @param clazz
     * @return T
     * @author King
     * @date 2018年11月13日
     */
    public static <T> T stringToBean(String str, Class<T> clazz) {
        if ((str == null) || (str.length() <= 0) || (clazz == null)) {
            return null;
        }
        if ((clazz == int.class) || (clazz == Integer.class)) {
            return (T) Integer.valueOf(str);
        } else if (clazz == String.class) {
            return (T) str;
        } else if ((clazz == long.class) || (clazz == Long.class)) {
            return (T) Long.valueOf(str);
        } else {
            return JSON.toJavaObject(JSON.parseObject(str), clazz);
        }
    }

    /**
     * 判断字符串是否为空 空的定义为 null 与""与多个""
     *
     * @param str
     * @return Boolean
     * @author King
     * @date 2020年8月13日
     */
    public static Boolean isEmpty(String str) {
        if (StrUtil.isEmpty(str)) {
            return StrUtil.isEmpty(str);
        }
        return StrUtil.isEmpty(str.trim());
    }

    public static String getDateTimeAsString(LocalDateTime localDateTime, String format) {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern(format);
        return localDateTime.format(formatter);
    }

    /**
     * 将需要发送的消息内容转为json格式
     *
     * @param openid
     * @param template_id
     * @param first
     * @param remark
     * @return
     * @author pj
     */
    public static JSONObject StringToJson(String openid, String template_id, TemplateData first,
                                          List<TemplateData> listTemplateDatas, String clickurl, TemplateData remark) {
        JSONObject json = new JSONObject();
        Map<String, Object> data = new HashMap<String, Object>();

        data.put("first", first);

        for (int i = 1; i <= listTemplateDatas.size(); i++) {
            data.put("keyword" + i, listTemplateDatas.get(i - 1));
        }
        data.put("remark", remark);
        json.put("url", clickurl);
        json.put("touser", openid);
        json.put("template_id", template_id);
        json.put("data", data);
        return json;
    }

    /**
     * 调用cmd命令。
     *
     * @param cmd 命令
     * @return 执行结果
     */
    public static String execcmd(String cmd) {
        Runtime run = Runtime.getRuntime();
        String szline = null;
        StringBuilder sb = new StringBuilder();
        try {
            // run.exec("cmd /k shutdown -s -t 3600");
            Process process = run.exec(cmd);

            InputStream input = process.getInputStream();
            BufferedReader reader = new BufferedReader(new InputStreamReader(input, "GBK"));
            while ((szline = reader.readLine()) != null) {
                sb.append(szline + "\n");
            }
            reader.close();
            process.waitFor();
            process.destroy();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return sb.toString();
    }


    /**
     * 获取某个文件夹下的所有文件
     *
     * @param fileNameList 存放文件名称的list
     * @param path         文件夹的路径
     * @return
     */
    public static ArrayList<String> getAllFileName(String path) {
        ArrayList<String> files = new ArrayList<String>();
        // boolean flag = false;
        File file = new File(path);
        File[] tempList = file.listFiles();

        for (File element : tempList) {
            if (element.isFile()) {
                // System.out.println("文 件：" + tempList[i]);
                // fileNameList.add(tempList[i].toString());
                files.add(element.getName());
            }
            if (element.isDirectory()) {
                // System.out.println("文件夹：" + tempList[i]);
                getAllFileName(element.getAbsolutePath());
            }
        }
        return files;
    }

    /**
     * 转换成map
     * @param list
     * @return
     */
    public static Map<String, Object> modelConversionMap(List<MapModel> list){
        Map<String, Object> map = new HashMap<>();
        if(list!=null && list.size()>0){
            for(MapModel mapModel:list){
                map.put(mapModel.getId(), mapModel.getValue());
            }
        }
        return map;
    }

    public static <T> Collection<T> selectIn(Collection<T> c,String field,Object param){
		BeanEqualPredicate<T> predicate = new BeanEqualPredicate<>(field, param);
		return CollectionUtils.select(c, predicate);
	}

    public static <T> Collection<T> selectNot(Collection<T> c,String field,Object param){
		BeanNotEqualPredicate<T> predicate = new BeanNotEqualPredicate<>(field, param);
		return CollectionUtils.select(c, predicate);
	}
}
